package com.example.healkep;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.camera2.Camera2Config;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraXConfig;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.example.healkep.MainActivity.MainActivityGetinFood;
import com.example.healkep.bean.Food;
import com.example.healkep.bean.dish;
import com.example.healkep.bean.dishResult;
import com.example.healkep.bean.globalUserInfo;
import com.example.healkep.datepicker.CustomDatePicker;
import com.example.healkep.datepicker.DateFormatUtils;
import com.example.healkep.listener.HttpListener;
import com.example.healkep.utils.HttpUtil;
import com.example.healkep.utils.Permission;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.lifecycle.LifecycleOwner;

import com.example.healkep.utils.baidu.Base64Util;
import com.example.healkep.weiget.bg.CircleImageView;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.gson.reflect.TypeToken;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class CameraActivity extends AppCompatActivity implements CameraXConfig.Provider{
    private PreviewView previewView;
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
    private CircleImageView shot;
    private ImageCapture imageCapture;
    private ImageView image;
    private Camera camera;
    private ProgressBar progressBar;
    private TextView cal,date;
    private Spinner name,type;
    private Button btn;
    private List<View> views;
    private dishResult result;
    private TextView select_from_file;
    private final  int REQUEST_TAKE_PHOTOES = 600;
    @SuppressLint("RestrictedApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        Permission.checkPermission(this);
        initComponent();
        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                bindPreview(cameraProvider);
            } catch (ExecutionException | InterruptedException e) {
                // No errors need to be handled for this Future.
                // This should never be reached.
            }
        }, ContextCompat.getMainExecutor(this));
        shot.setOnClickListener((view)->{
            imageCapture.takePicture(CameraXExecutors.mainThreadExecutor(),new ImageCapture.OnImageCapturedCallback() {
                @Override
                public void onCaptureSuccess(@NonNull ImageProxy image) {
                    super.onCaptureSuccess(image);
                    Bitmap b = previewView.getBitmap();
                    success(b);
                }

                @Override
                public void onError(@NonNull ImageCaptureException exception) {
                    super.onError(exception);
                }
            });
        });
    }
    private void success(Bitmap bitmap){
        previewView.setVisibility(View.GONE);
        shot.setVisibility(View.GONE);
        CameraActivity.this.image.setImageBitmap(bitmap);
        int quality = 10;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        byte[] bytes = baos.toByteArray();
        String imgStr = Base64Util.encode(bytes);
        HttpUtil<dishResult> helper = new HttpUtil<>();
        Map<String, Object> map = new HashMap<>();
        map.put("img",imgStr);
        helper.post(LoginActivity.url + "/dish", helper.getRequestBody(map), new HttpListener<dishResult>() {
            @Override
            public void success(dishResult data) {
                result = data;
                progressBar.setVisibility(View.GONE);
                for(View i : views){
                    i.setVisibility(View.VISIBLE);
                }
                ArrayList<String> list = new ArrayList<>();
                for(dish i :data.getResult()){
                    list.add(String.format("%s(%2.2f%%)",i.getName(),i.getProbability()*100));
                }
                ArrayAdapter<String> adapter=new ArrayAdapter<String>(CameraActivity.this,android.R.layout.simple_spinner_item, list.toArray(new String[0]));
                adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                cal.setText(String.valueOf(data.getResult().get(0).calorie));
                name.setAdapter(adapter);
                name.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                        dish d = data.getResult().get(position);
                        if(d.has_calorie)
                            cal.setText(String.valueOf(data.getResult().get(position).calorie));
                        else
                            cal.setText("0");
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?> parent) {

                    }
                });
            }

            @Override
            public void failed(int code, String message, String detailMessage) {
                Toast.makeText(CameraActivity.this,message,Toast.LENGTH_SHORT).show();
            }
        },dishResult.class,CameraActivity.this);
    }
    void initComponent(){
        previewView = findViewById(R.id.previewView);
        shot = findViewById(R.id.shot);
        image = findViewById(R.id.image);
        progressBar = findViewById(R.id.progress);
        date = findViewById(R.id.dish_date);
        cal = findViewById(R.id.dish_per_cal);
        name = findViewById(R.id.dish_name);
        type = findViewById(R.id.dish_type);
        btn = findViewById(R.id.btn_submit);
        views = new ArrayList<>();
        views.add(findViewById(R.id.layout_cal));
        views.add(findViewById(R.id.layout_date));
        views.add(findViewById(R.id.layout_name));
        views.add(findViewById(R.id.layout_type));
        select_from_file = findViewById(R.id.select_from_file);
        views.add(btn);
        String[] mItems = getResources().getStringArray(R.array.food_time);
        ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, mItems);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        type.setAdapter(adapter);
        String beginTime = "2018-00-00 00:00";
        String endTime = DateFormatUtils.long2Str(System.currentTimeMillis(), true);
        date.setText(endTime);
        date.setOnClickListener((i)->{
            new CustomDatePicker(CameraActivity.this, new CustomDatePicker.Callback() {
                @Override
                public void onTimeSelected(long timestamp) {
                    date.setText(DateFormatUtils.long2Str(timestamp, true));
                }
            }, beginTime, endTime).show(endTime);
        });
        for(View i : views){
            i.setVisibility(View.GONE);
        }
        btn.setOnClickListener((v)->{
            dish d = result.getResult().get(name.getSelectedItemPosition());
            if(d.getName().equals("非菜")){
                Toast.makeText(CameraActivity.this,"识别失败，无法上传",Toast.LENGTH_SHORT).show();
                return;
            }
            String time = date.getText().toString();
            int time_slot = type.getSelectedItemPosition()+1;
            final String json ="{\n" +
                    "    \"user\":\""+ globalUserInfo.getInstance().getUsername()+"\",\n" +
                    "    \"time_slot\":\""+time_slot+"\",\n" +
                    "    \"id\":\""+d.getName()+"\",\n" +
                    "    \"cal\":\""+(int)d.getCalorie().floatValue()+"\",\n" +
                    "    \"cdate\":\""+time+"\"\n" +
                    "}";
            new Thread ( new Runnable () {
                @Override
                public void run() {
                    try{
                        OkHttpClient client = new OkHttpClient (  );
                        Request request = new Request.Builder (  )
                                .url ( com.example.healkep.LoginActivity.url+"/food2/add" )
                                .post ( RequestBody.create ( MediaType.parse ( "application/json"),json  ) )
                                .build ();
                        Response response = client.newCall ( request ).execute ();
                        runOnUiThread ( new Runnable () {
                            @Override
                            public void run() {
                                Toast.makeText ( CameraActivity.this, "发送成功" , Toast.LENGTH_SHORT).show ();

                            }
                        } );
                    }catch (Exception e){
                        e.printStackTrace ();
                        runOnUiThread ( new Runnable () {
                            @Override
                            public void run() {
                                Toast.makeText ( CameraActivity.this, "网络连接失败", Toast.LENGTH_SHORT).show ();
                            }
                        } );
                    }
                }
            } ).start ();
        });

        select_from_file.setOnClickListener((v)->{
            Intent gallery = new Intent(Intent.ACTION_PICK);
            gallery.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
            startActivityForResult(gallery, REQUEST_TAKE_PHOTOES);
        });
    }

    void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
        Preview preview = new Preview.Builder()
                .build();
        CameraSelector cameraSelector = new CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                .build();

        preview.setSurfaceProvider(previewView.getSurfaceProvider());
        imageCapture =
                new ImageCapture.Builder()
                        .setTargetRotation(previewView.getDisplay().getRotation())
                        .build();
        camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector,imageCapture, preview);

    }
    @Override
    protected void onResume(){
        super.onResume();
        if(Permission.isPermissionGranted(this)){

        }
    }
    @Override
    public void onRequestPermissionsResult(
            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == Permission.REQUEST_CODE) {
            for (int grantResult : grantResults) {
                if (grantResult != PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this, "没有相机访问权限，请到设置中给予权限后重试",Toast.LENGTH_SHORT).show();
                    this.finish();
                    return;
                }
            }
        }
    }

    @NonNull
    @Override
    public CameraXConfig getCameraXConfig() {
        return  CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
                .build();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_TAKE_PHOTOES) {
            if (data != null) {
                // 得到图片的全路径
                Uri uri = data.getData();
                ContentResolver resolver = getContentResolver();
                try {
                    //使用ContentProvider通过URI获取原始图片
                    Bitmap bitmap= MediaStore.Images.Media.getBitmap(resolver, uri);
                    success(bitmap);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}